package scene;

import geometrie.Point;
import geometrie.Rebouchage;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Class responsible for treating the .off files, i.e, translating the files to
 * a Facette3D that can to be seem in the screen.
 * 
 */
public class ModeleMaillage implements Modele3D {
	private List<Facette3D> facettes;

	public Iterator<Facette3D> getFacettes() {
		return facettes.listIterator();
	}

	/**
	 * Receives a .off file name and produces a list of faces with the points
	 * given in the file.
	 * 
	 * @param fileName
	 *            The file
	 */
	public ModeleMaillage(String fileName) {

		facettes = new ArrayList<Facette3D>();
		try {
			BufferedReader in = new BufferedReader(new FileReader(fileName));
			String vertexString;
			String facetteString;
			in.readLine();
			int i = 0;
			int[] facesVertexArray = getNumFacesVertex(in.readLine());
			Point[] vertexArray = new Point[facesVertexArray[0]];
			while (i < facesVertexArray[0]) {
				vertexString = in.readLine();
				vertexArray[i] = fromStringToPoint(vertexString);
				i++;
			}
			i = 0;
			while (i < facesVertexArray[1]) {
				facetteString = in.readLine();
				facettes.add(treatFacetteString(facetteString, vertexArray));
				i++;
			}
			in.close();
		} catch (IOException e) {
			System.err.println("Invalid input file.");
		}
	}

	/**
	 * Convert a String in the format "coordX coordY coordZ" and transforms it
	 * into a Point type
	 * 
	 * @param str
	 *            The string to be converted to a point type
	 * @return the point
	 */
	static private Point fromStringToPoint(String str) {

		int size = str.length();
		int index1 = 0, index2;
		index2 = str.indexOf(" ", index1);
		String x = str.substring(index1, index2);
		index1 = new Integer(index2) + 1;
		index2 = str.indexOf(" ", index1);
		String y = str.substring(index1, index2);
		index1 = new Integer(index2) + 1;
		index2 = size;
		String z = str.substring(index1, index2);
		return new Point(10*Double.valueOf(x), 10*Double.valueOf(y),
				10*Double.valueOf(z));
	}

	/**
	 * Gets second line of .off file and obtains the number of faces and the
	 * number of vertices
	 * 
	 * @param line
	 *            The second line
	 * @return Number of faces and number of vertices
	 */
	static private int[] getNumFacesVertex(String line) {

		int[] facesVertexArray = new int[2];
		String stringNumVertex, stringNumFaces;
		int index1 = 0, index2;
		index2 = line.indexOf(" ", index1);
		stringNumVertex = line.substring(index1, index2);
		index1 = new Integer(index2) + 1;
		index2 = line.indexOf(" ", index1);
		stringNumFaces = line.substring(index1, index2);
		facesVertexArray[0] = Integer.valueOf(stringNumVertex);
		facesVertexArray[1] = Integer.valueOf(stringNumFaces);
		return facesVertexArray;
	}
	
	public void addTriangulation(Point[] polygon) {
		facettes.addAll(Rebouchage.rebouchageTrouRecCache(polygon));
	}

	/**
	 * Gets String of type "numPoints Point1 Point2 ... Pointn" and returns a
	 * face produced by these points. In our case, numPoints = 3, and thus, the
	 * facet will be a triangle.
	 * 
	 * @param str
	 *            The string in the type above
	 * @param vertexArray
	 *            A array with the vertices of the figure
	 * @return A triangular facet represented by Facette3D
	 */
	static private Facette3D treatFacetteString(String str, Point[] vertexArray) {

		int size = str.length();
		int v1, v2, v3;
		int index1 = 0, index2;
		index2 = str.indexOf(" ", index1);
		index1 = index2 + 1;
		if(str.charAt(index1) == ' ')
		{
			index1++;
		}
		index2 = str.indexOf(" ", index1);
		v1 = Integer.valueOf(str.substring(index1, index2));
		index1 = index2 + 1;
		index2 = str.indexOf(" ", index1);
		v2 = Integer.valueOf(str.substring(index1, index2));
		index1 = index2 + 1;
		index2 = size;
		v3 = Integer.valueOf(str.substring(index1, index2));
		return new Facette3D(vertexArray[v1], vertexArray[v2], vertexArray[v3]);
	}
}
